﻿

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

using MicroCenter.Hubs;
using MicroCenter.Models;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Options;

using Utils;


namespace MicroCenter.Services
{
    [Injection(Microsoft.Extensions.DependencyInjection.ServiceLifetime.Singleton), JobService]
    public class MicroService
    {
        private static Dictionary<string, RegistryModel> _registries = new Dictionary<string, RegistryModel>();

        public readonly IHubContext<MicroHub> hubContext;

        public readonly IWritableOptions<MicroCenterOptions> writableOptions;

        public readonly NginxService nginxService;

        /// <summary>
        /// 已经创建账户
        /// </summary>
        /// <returns></returns>
        public bool IsInit()
        {
            return !writableOptions.Value.RootKey.IsNullOrEmpty();
        }


        public string Login(LoginDTO dto)
        {
            VerifyUtil.Verify(dto)
                .Required(a => a.UserName)
                .Required(a => a.Password)
                .IsMatch(a => a.UserName, () => dto.UserName != "root")
                .IsMatch(a => a.Password, () => !dto.Password.ToMD5().Equals(writableOptions.Value.RootKey))
                .ThrowInputError();
            return dto.Password.ToMD5();
        }


        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="password"></param>
        /// <param name="oldPassword"></param>
        public void UpdatePassWord(ChangePasswordDTO dto)
        {

            if (!IsInit())
            {
                VerifyUtil.Verify(dto)
                    .Required(a => a.Password)
                    .Required(a => a.RePassword)
                    .IsMatch(a => a.Password, () => dto.Password.Length < 4, "密码长度最小4位")
                    .IsMatch(a => a.RePassword, () => dto.RePassword != dto.Password, "确认密码不一致")
                    .ThrowInputError();
                writableOptions.Update(options =>
                {
                    options.RootKey = dto.Password.ToMD5();
                    return true;
                });
            }
            else
            {
                VerifyUtil.Verify(dto)
                         .Required(a => a.Password)
                         .Required(a => a.OldPassword)
                         .Required(a => a.RePassword)
                         .IsMatch(a => a.Password, () => dto.Password.Length < 4, "密码长度最小4位")
                         .IsMatch(a => a.OldPassword, () => dto.OldPassword.ToMD5() != writableOptions.Value.RootKey, "旧密码有误")
                         .IsMatch(a => a.RePassword, () => dto.RePassword != dto.Password, "确认密码不一致")
                         .ThrowInputError();
                writableOptions.Update(options =>
                {
                    options.RootKey = dto.Password.ToMD5();
                    return true;
                });
            }

        }
        public bool CheckAccessToken(HttpContext context)
        {
            try
            {
                var secret = writableOptions.Value.Secret;
                var t = context.Request.Query["t"].ToString();
                var accessToken = context.Request.Query["access_token"].ToString();
                return accessToken.Equals((t + secret).ToMD5());
            }
            catch
            {
                return false;
            }
        }
        public void Registry(string clientId, RegistryModel model)
        {
            _registries[clientId] = model;
            SendAll();
        }

        public void SendAll()
        {
            var registryModels = GetRegistries();
            hubContext.Clients.All.SendAsync("ReLoad", registryModels);
            try
            {
                nginxService.ReloadConfig(registryModels);
            }
            catch
            {
            }

        }

        public RegistryModel[] GetRegistries()
        {
            return _registries.Select(a => a.Value).ToArray();
        }

        public void Remove(string clientId)
        {
            if (_registries.ContainsKey(clientId))
                _registries.Remove(clientId);
            SendAll();
        }


    }
}
